// author: Shelman
// description: 封装的使用posix接口实现的TCP客户端
#pragma once

#include <iostream>
#include <string>
#include <functional>
#include <thread>
#include <mutex>
#include <atomic>
#include <queue>

#include "GlobalDef.h"


// TCP客户端
class TcpClient
{
public:
    /*****************************************************
     * 功能：构造函数
     * ***************************************************/
    TcpClient();

    /*****************************************************
     * 功能：析构函数
     * ***************************************************/
    virtual ~TcpClient();

    /*****************************************************
     * 功能：不主动调用read接口获取数据时，设置接收数据的回调，
     * 输入参数：
     *      pfnCallback：数据回调函数
     * ***************************************************/
    void setDataRecvCallback(const DataReceivedCallback &pfnCallback);

    /*****************************************************
     * 功能：与服务端进行连接
     * 输入参数：
     *      stConnInfo：服务端的连接信息
     *      bAutoReconnect：是否自动重连，true -- 自动重连，false -- 不自动重连
     * 返回值：
     *      bool：连接结果，true -- 连接成功，false -- 连接失败
     * ***************************************************/
    bool connect(const NetworkConnInfo &stSrvConnInfo, bool bAutoReconnect);

    /*****************************************************
     * 功能：断开与服务端的连接
     * ***************************************************/
    void disconnect();

    /*****************************************************
     * 功能：向服务端发送数据
     * 输入参数：
     *      strData：待发送的数据
     * 返回值：
     *      bool：发送结果，true -- 发送成功，false -- 发送失败
     * ***************************************************/
    bool sendData(const std::string &strData);

    /*****************************************************
     * 功能：向服务端读取数据
     * 输出参数：
     *      strData：待读取的数据的缓存区
     * 返回值：
     *      bool：读取结果，true -- 读取成功，false -- 读取失败
     * ***************************************************/
    bool recvData(std::string &strData);

private:
    /*****************************************************
     * 功能：初始化socket
     * ***************************************************/
    bool initSocket();

    /*****************************************************
     * 功能：清理资源
     * ***************************************************/
    void cleanup();

    /*****************************************************
     * 功能：连接服务端
     * 返回值：
     *      bool：连接结果，true -- 连接成功，false -- 连接失败
     * ***************************************************/
    bool connectToServer();

    /*****************************************************
     * 功能：重新连接服务端
     * ***************************************************/
    void reconnectServer();

    /*****************************************************
     * 功能：异步IO线程业务处理接口
     * ***************************************************/
    void onAsyncIOThread();

private:
    bool m_bAutoReconn = true; // 是否自动重连的标识
    std::atomic<bool> m_bConnected; // 是否与服务端已连接的标识
    std::atomic<bool> m_bRunning;   // 客户端运行状态标识

    NetworkConnInfo m_stSrvConnInfo; // 服务端连接信息
    int m_fdSock = -1; // socket连接句柄

    std::mutex m_mt4SendData; // 发送数据互斥锁
    std::mutex m_mt4RecvData; // 接收数据互斥锁

    std::thread m_th4AsyncIO; // 异步处理线程

    std::mutex m_mt4PfnCallback;          // 回调函数互斥锁
    DataReceivedCallback m_pfn4RecvDataCb; // 数据接收回调函数

};

